require File.join(File.dirname(__FILE__),'dump.rb')

class Serializer
    @@KEY_SIZE = 2
    @@FLAGS_SIZE = 1
    @@VALUE_SIZE = 3
    
    def self.serialize(key, flags, value)
        s = []
        write_key(s, key)
        write_flags(s, flags)
        write_value(s, value)
        s
    end

    def self.deserialize(file)
        open(file, "rb") do |f|
            while ((a = f.getc) != nil) do
                key = read_key(f, a)
                flags = read_flags(f)
                value = read_value(f)
                if block_given?
                    yield key, flags, value
                else
                    return key, flags, value
                end
            end
        end
    end

    def self.read_key(f, a)
        key_size = ""
        key_size << a
        (@@KEY_SIZE-1).times {key_size << f.getc}
        key_length = to_int(key_size)
        key = ""
        key_length.times{key << f.getc}
	key
    end

    def self.read_flags(f)
        read_data(f, @@FLAGS_SIZE)
    end

    def self.read_value(f)
        read_data(f, @@VALUE_SIZE)
    end

    def self.read_data(f, size_length)
        size = ""
        size_length.times{size << f.getc}
        length = to_int(size)
        data = ""
        length.times{data << f.getc}
        data
    end

    def self.to_bytes(num, length)
        num.to_s(16)[0..2].instance_eval {(self.reverse + '0' * (2*length -
                self.length)).reverse}.scan(/../).inject('') {|s, byte| s <<
                byte.to_i(16)}
    end

    def self.write_key(s, key)
        s << to_bytes(key.length, @@KEY_SIZE)
        s << key
    end

    def self.write_flags(s, flags)
        s << to_bytes(flags.length, @@FLAGS_SIZE)
        s << flags
    end

    def self.write_value(s, value)
        s << to_bytes(value.length, @@VALUE_SIZE)
        s << value

    end

    def self.to_int(s)
        s.unpack('H*').first.to_i(16)
    end

    def self.write_key(s, key)
        s << to_bytes(key.length, @@KEY_SIZE)
        s << key
    end

    def self.write_flags(s, flags)
        s << to_bytes(flags.length, @@FLAGS_SIZE)
        s << flags
    end

    def self.write_value(s, value)
        s << to_bytes(value.length, @@VALUE_SIZE)
        s << value
    end

end
